﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PMatch;
using PMatch.Formats.SequenceSample;

namespace hmmtrain
{
	class Program
	{
		static void Main(string[] args)
		{
			ExecSettings settings;
			ParseArguments(args, out settings);
			try
			{
				Execute(settings);
			}
			catch (Exception ex)
			{
				var eex = ex;
				do
				{
					Console.Error.WriteLine(ex.Message + "\n");
				} while ((eex = eex.InnerException) != null);
			}
		}

		private static void Execute(ExecSettings settings)
		{
			var ifile = samples.LoadFromFile(settings.Input);
			
			var positive = ifile.positive;
			var negative = ifile.negative;

			Console.WriteLine("Muestras positivas: {0}", positive.Count());
			Console.WriteLine("Muestras negativas: {0}", negative.Count());
			Console.WriteLine("Tolerance: {0} | States: {1}", settings.Rtol, settings.States);
			Console.WriteLine("Entrenando modelo...");

			var model = new MarkovModel(settings.States, settings.Rtol, HMMType.Ergodic);
			model.Train(ifile);
			model.SaveToFile(settings.Output);
			Console.WriteLine("Modelo escrito: {0}", settings.Output);
		}

		private static void ParseArguments(string[] args, out ExecSettings settings)
		{
			if (args.Length < 4)
			{
				ShowUsage();
				Environment.Exit(255);
			}

			settings = new ExecSettings();
			settings.Rtol = double.Parse(args[0]);
			settings.States = int.Parse(args[1]);
			settings.Input = args[2];
			settings.Output = args[3];
		}


		/// <summary>
		/// Muestra como se usa el programa por la consola
		/// </summary>
		private static void ShowUsage()
		{
			var help =
@"hmmtrain Trains a Hidden Markov Model based classifier
from a dataset containing positive and negative samples

	hmmtrain rtol nstates input output 
 
	input: Input file with sample dataset
	output: Output file with HMM-classifier trained
	nstates: States number of the HMM-classifier
	rtol: Tolerance of training (default: 1e-5)
";
			Console.WriteLine(help);
		}
	}

	class ExecSettings
	{
		public string Input { get; set; }
		public string Output { get; set; }
		public int States { get; set; }
		public double Rtol { get; set; }
	}
}
